package com.crazymaker.springcloud.websocket.client;

import com.crazymaker.springcloud.common.constants.SessionConstants;
import com.crazymaker.springcloud.common.util.JsonUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
 * 基于websocket的netty客户端
 */
public class WebSocketMockClient {
    static int appId=1;
//    static   String  uriString = "ws://127.0.0.1:9999/push";
//    static   String  uriString = "ws://cdh2:9999/push";
    static   String  uriString = "ws://cdh2:9989/push";
    static   String clinetToken =
"eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIxODYwMDAwMDAwIiwiZXhwIjoxNjQ4Mzk0NDEyLCJpYXQiOjE2NTAwOTczNzl9.UohiLJQ9KuZou4M-cK_5_GbPmQYB71AgYIBNKHwE3bcEmiYBExN6dyfj1YRmpQwLyNhj3Z2w2iGsB0Xs7CZ0fa2e_x2AI5JpCcc4-1dNncyzYlFe4u9QALqmxQnsL1uKU7WS8cu8WfAq6k5kQph-dRuvVcpXJL66dCPgQhvTasxbG-OAHLfYttU-lAgLDRKQ06C078Q6IqNUumAF8uVZPDwr_hQPb9wAqEM6JE0kvET_1WbK0Vw6kJanRzfTqEF2VGJypmPMpaME2JZ69zVuykNYH25Tt4JqUqj2qmdvjjSCzVKV87hGSjYhLQtLikLKg5Z-f5QL15QIMXeUnSP0AA";


    public static void main(String[] args) throws Exception {
        //netty基本操作，线程组
        EventLoopGroup group = new NioEventLoopGroup();
        //netty基本操作，启动类
        Bootstrap boot = new Bootstrap();
        boot.option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.TCP_NODELAY, true)
                .group(group)
                .handler(new LoggingHandler(LogLevel.INFO))
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast("http-codec", new HttpClientCodec());
                        pipeline.addLast("aggregator", new HttpObjectAggregator(1024 * 1024 * 10));
                        pipeline.addLast("ws-handler", new WebSocketClientHandler());
                    }
                });
        //websocke连接的地址，/push  是因为在服务端的websockethandler设置的
        URI websocketURI = new URI(uriString);
        HttpHeaders httpHeaders = new DefaultHttpHeaders();
        httpHeaders.set(SessionConstants.AUTHORIZATION_HEAD, clinetToken);
        httpHeaders.set(SessionConstants.APP_ID, appId);
        //进行握手
        WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(websocketURI, WebSocketVersion.V13, (String) null, true, httpHeaders);
        //客户端与服务端连接的通道，final修饰表示只会有一个
        final Channel channel = boot.connect(websocketURI.getHost(), websocketURI.getPort()).sync().channel();
        WebSocketClientHandler handler = (WebSocketClientHandler) channel.pipeline().get("ws-handler");
        handler.setHandshaker(handshaker);
        handshaker.handshake(channel);
        //阻塞等待是否握手成功
        handler.handshakeFuture().sync();
        System.out.println("握手成功");
        //给服务端发送的内容，如果客户端与服务端连接成功后，可以多次掉用这个方法发送消息
        sengMessage(channel);
    }

    public static void sengMessage(Channel channel) {

        Map<String, String> map = new HashMap<>();
        map.put("type", "msg");
        map.put("msg", "你好，来自应用 " + appId);
        //发送的内容，是一个文本格式的内容
        String putMessage = JsonUtil.pojoToJson(map);
        TextWebSocketFrame frame = new TextWebSocketFrame(putMessage);
        channel.writeAndFlush(frame).addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()) {
                    System.out.println("消息发送成功，发送的消息是：" + putMessage);
                } else {
                    System.out.println("消息发送失败 " + channelFuture.cause().getMessage());
                }
            }
        });
    }

}